#include "twebsocketserver.h"
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QTextEdit>
#include <QDateTime>
#include <QFile>
#include <QDebug>
#define THREADNUM 1
TWebSocketServer::TWebSocketServer(QWidget *parent)
    : QMainWindow(parent)
    , m_pHost(new QLabel(this))
    , m_pIp(new QLabel(this))
    , m_pHostLineEdit(new QLineEdit(this))
    , m_pIpLineEdit(new QLineEdit(this))
    , m_pStartButton(new QPushButton(this))
    , m_pCloseButton(new QPushButton(this))
    , m_pTextEdit(new QTextEdit(this))
    , m_pDisplayTextEdit(new QTextEdit(this))
{
    server = nullptr;
    service = nullptr;
    ws = nullptr;
    initUI();
    initConnect();
    resize(500,500);
}

void TWebSocketServer::initConnect()
{
    connect(m_pStartButton, &QPushButton::released, [this]() {
        std::string host = m_pHostLineEdit->text().toStdString();
        int port = m_pIpLineEdit->text().toInt();

        if (start(port, host.c_str())) {
            m_pStartButton->setEnabled(false);
            m_pCloseButton->setEnabled(true);
            m_pDisplayTextEdit->append(QString("HTTP server running on ")+QString::fromStdString(host));
        }
        else {
            stop();
            m_pDisplayTextEdit->append(QString("HTTP server start failed!"));
        }
    });

    connect(m_pCloseButton, &QPushButton::released, [this]() {
        stop();
        m_pStartButton->setEnabled(true);
        m_pCloseButton->setEnabled(false);
        m_pDisplayTextEdit->append(QString("HTTP server stopped!"));

    });
}

bool TWebSocketServer::start(int port, const char* host)
{
    service = new hv::HttpService;
    service->document_root = ".";
    service->home_page = "index.html";

    service->preprocessor = [this](HttpRequest* req, HttpResponse* resp) {
        std::cout << "received http request:\n" << req->Dump(true, false) << std::endl;
        return 0;
    };

    service->POST("/echo", [this](const HttpContextPtr& ctx) {
        Json::CharReaderBuilder reader;
        Json::Value parsedRoot;
        std::string errs;
        std::istringstream s(ctx->body());
        if (Json::parseFromStream(reader, s, &parsedRoot, &errs))
        {
            std::cout << parsedRoot["cmd"].asString() << std::endl;
            //std::cout << parsedRoot["image-type"].asString() << std::endl;
            if (parsedRoot["content"].asString().empty())
            {
                std::cout << parsedRoot["image-name"].asString() << std::endl;
                bool flag = stringToImage(parsedRoot["image"].asString(), parsedRoot["image-name"].asString());
            }
            else if (parsedRoot["image"].asString().empty())
                std::cout << parsedRoot["content"].asString() << std::endl;
        }
        return ctx->send("already received.", ctx->type());
    });


    service->GET("/get", [](const HttpContextPtr& ctx) {
        std::string response_body = "GET request received";
        Json::Value root;
        root["content"] = response_body;
        Json::StreamWriterBuilder writer;
        std::string outputString = Json::writeString(writer, root);
        http_content_type type = APPLICATION_JSON;
        return ctx->send(outputString, type);
    });


    service->PUT("/put", [](const HttpContextPtr& ctx) {
        std::string response_body = "PUT request received";
        http_content_type type1 = TEXT_PLAIN;
        return ctx->send(response_body, type1);
    });

    service->Delete("/delete", [](const HttpContextPtr& ctx) {
        std::string response_body = "Delete request received";
        http_content_type type2 = TEXT_PLAIN;
        return ctx->send(response_body, type2);
    });

    service->PATCH("/patch", [](const HttpContextPtr& ctx) {
        std::string response_body = "PATCH request received";
        http_content_type type = TEXT_PLAIN;
        return ctx->send(response_body, type);
    });

    service->HEAD("/head", [](const HttpContextPtr& ctx) {
        std::string response_body = "HEAD request received";
        http_content_type type = TEXT_PLAIN;
        return ctx->send(response_body, type);
    });

    service->postprocessor = [this](HttpRequest* req, HttpResponse* resp) {
        std::cout << "send http response:\n" << resp->Dump(true, true) << std::endl;
        return 0;
    };
    //响应Http请求



    ws = new hv::WebSocketService;
    ws->onopen = [this](const WebSocketChannelPtr& channel, const HttpRequestPtr& req) {
        m_pDisplayTextEdit->append(QString("websocket open: ") + QString::fromStdString(req->Path()));
    };
    ws->onmessage = [this](const WebSocketChannelPtr& channel, const std::string& msg) {
        //显示客户端请求并响应
        Json::CharReaderBuilder reader;
        Json::Value parsedRoot;
        std::string errs;
        std::istringstream s(msg);
        if (Json::parseFromStream(reader, s, &parsedRoot, &errs))
        {
            QString qCmd;
            if(parsedRoot["cmd"].asInt()==0)
                qCmd = "初始化连接";
            else if(parsedRoot["cmd"].asInt() == 1)
                qCmd = "发送消息";
            else if (parsedRoot["cmd"].asInt() == 2)
                qCmd = "发送图片";
            //m_pDisplayTextEdit->append(QString("websocket receive: ") + qCmd + "\n" + QString::fromStdString(msg));
            qDebug() << QString("websocket receive: ") + qCmd + "\n" + QString::fromStdString(msg);

            switch (intTocmd(parsedRoot["cmd"].asInt()))
            {
            case cmd::INITCON:  initClientInfo(parsedRoot["id"].asString(), channel);   break;
            case cmd::SEND:     sendMsg(parsedRoot["content"].asString());              break;
            case cmd::SENDIMG:  saveImage(parsedRoot["image"].asString(), parsedRoot["image-name"].asString()); break;
            default:            m_pDisplayTextEdit->append(QString("未知命令"));         break;
            }
        }
        else std::cout << "解析失败" << std::endl;
    };
    ws->onclose = [this](const WebSocketChannelPtr& channel) {
        m_pDisplayTextEdit->append("websocket close");
    };

    server = new hv::WebSocketServer;
    server->registerHttpService(service);
    server->registerWebSocketService(ws);
    server->setHost(host);
    server->setPort(port);
    server->setThreadNum(THREADNUM);
    return server->start() == 0;
    //响应WebScoket请求
}

void TWebSocketServer::initClientInfo(const std::string& id, const WebSocketChannelPtr& channel)
{
    std::cout << id <<" 连接成功" << std::endl;
    clientMap[id] = channel;
}

void TWebSocketServer::sendMsg(const std::string& content)
{
    Json::Value root;
    root["content"] = content;
    Json::StreamWriterBuilder writer;
    std::string outputString = Json::writeString(writer, root);

    //向Map内所有的客户端发送指定内容
    for (const auto& client : clientMap)
    {
        std::cout << outputString << std::endl;
        client.second->send(outputString);
    }
}

void TWebSocketServer::saveImage(const std::string& image, const std::string& imageName)
{
    std::cout << imageName << std::endl;
    bool flag = stringToImage(image, imageName);
}

void TWebSocketServer::stop()
{
    SAFE_DELETE(server);
    SAFE_DELETE(service);
    SAFE_DELETE(ws);
}

cmd TWebSocketServer::intTocmd(int i)
{
    return static_cast<cmd>(i);
}

httpCmd TWebSocketServer::httpCmdToInt(int i)
{
    return static_cast<httpCmd>(i);
}


void TWebSocketServer::initUI()
{
    m_pHost->resize(30, 20);
    m_pHost->move(10, 20);
    m_pHost->setText("Host");

    m_pIp->resize(30, 20);
    m_pIp->move(300, 20);
    m_pIp->setText("IP");

    m_pHostLineEdit->resize(150,20);
    m_pHostLineEdit->move(50, 20);
    m_pHostLineEdit->setText("0.0.0.0");

    m_pIpLineEdit->resize(150, 20);
    m_pIpLineEdit->move(340, 20);
    m_pIpLineEdit->setText("9999");

    m_pStartButton->resize(80, 20);
    m_pStartButton->move(50, 50);
    m_pStartButton->setText("Start");

    m_pCloseButton->resize(80, 20);
    m_pCloseButton->move(150, 50);
    m_pCloseButton->setText("Close");

    m_pTextEdit->resize(400, 200);
    m_pTextEdit->move(10, 80);


   /* m_pSendButton->resize(40, 30);
    m_pSendButton->move(420, 150);
    m_pSendButton->setText("Send");*/

    m_pDisplayTextEdit->resize(480, 200);
    m_pDisplayTextEdit->move(10, 290);
}

bool TWebSocketServer::stringToImage(const std::string& base64Image,const std::string& name)
{
    QByteArray binaryData = QByteArray::fromBase64(QString::fromStdString(base64Image).toUtf8());
    if (binaryData.isEmpty()) {
        std::cout << "Base64解码失败，得到的二进制数据为空" << std::endl;
        return false;
    }
    QString dateTimeString = QDateTime::currentDateTime().toString("yyMMddhhmmss");
    QFile outputFile(dateTimeString + QString::fromStdString(name));//设置文件名称
    if (outputFile.open(QIODevice::WriteOnly)) {
        outputFile.write(binaryData);
        outputFile.close();
        std::cout << "图片解码成功并保存" << std::endl;
        return true;
    }
    else {
        std::cout << "无法打开文件以写入解码后的图片" << std::endl;
        return false;
    }
}

TWebSocketServer::~TWebSocketServer()
{
    stop();
}

